enchant();

var MUTEKI = false;
var SCROLL_SPEED = 1.5;

var Dtype = {};
Dtype.game = null;
Dtype.stage = null;
Dtype.map = null;
Dtype.myFighter = null;
Dtype.bullets = [];
Dtype.enemies = [];
Dtype.enemyBullets = [];

// sound
Dtype.sound = {};
//Dtype.sound.explode = Sound.load("explode.mp3");
Dtype.sound.explode = null;

var enemyData;

window.onload = function() {
    Dtype.game = new Game(320, 320);

    enemyData = loadEnemyData();

    var game = Dtype.game;
    game.fps = 24;
    game.preload([ "chara1.gif", "explosion1.png", "explosion2.png", "map2.gif" ]);
    game.rootScene.backgroundColor = "#000";
    game.keybind(90, "a");
    game.keybind(88, "b");
    game.score = 0;
    game.onload = function() {
        game.rootScene.addChild(createBackground());

        Dtype.stage = new Group();
        var stage = Dtype.stage;
        game.rootScene.addChild(stage);

        Dtype.myFighter = new Sprite(32, 32);
        var myFighter = Dtype.myFighter;
        stage.addChild(myFighter);

        // map
        Dtype.map = createMap();
        var map = Dtype.map;
        stage.addChild(map);

        // enemy pool
        for (var i = 0; i < 20; i++) {
            Dtype.enemies.push(new Enemy());
        }

        // enemy bullet pool
        for (var i = 0; i < 20; i++) {
            Dtype.enemyBullets.push(new EnemyBullet());
        }
        
        // bullet pool
        for (var i = 0; i < 6; i++) {
            Dtype.bullets.push(new RailGun());
        }
        
        // myFighter
        myFighter.image = game.assets["chara1.gif"];
        myFighter.rotation = 90;
        myFighter.padX = 5;
        myFighter.padY = 10;
        myFighter.hitSize = 10;

        myFighter.x = game.width / 2 - myFighter.width / 2;
        myFighter.y = game.height / 2 - myFighter.height / 2;
        myFighter.frame = 0;
        myFighter.heat = 0;

        myFighter.speed = 5;
        myFighter.shotSpeed = 6;

        myFighter.move = function(vx, vy) {
            var dest = {
                left: this.x + vx + this.padX,
                top: this.y + vy + this.padY,
                width: this.width - this.padX*2,
                height: this.height - this.padY*2
            };
            if (this.y + this.vy < 0) dest.top = 0;

            var dx = Math.floor(dest.width / 2);
            var dy = Math.floor(dest.height / 2);
            for(var i = 0; i < 20; i++) {
                var hit = 0;
                for (var y = 0; y <= dest.height; y += dy) {
                    for (var x = 0; x <= dest.width; x += dx) {
                        hit <<= 1;
                        hit |= map.hitTest(dest.left + x - map.x, dest.top + y);
                    }
                }
                if (hit) console.log("hit" + hit);
                if (hit == 0) {
                    break;
                } else if ((hit & 0700) == 0) {
                    dest.top -= 1;
                } else if ((hit & 0007) == 0) {
                    dest.top += 1;
                } else if ((hit & 0444) == 0) {
                    dest.left -= 1;
                    if (dest.left < 0) {
                        // Sandwiched between the wall
                        this.miss();
                        return;
                    }
                } else if ((hit & 0111) == 0) {
                    dest.left += 1;
                } else {
                    dest.left -= vx;
                    dest.top -= vy;
                }
            }

            if (i < 20) {
                this.x = dest.left - this.padX;
                this.y = dest.top - this.padY;
            }
        };
        myFighter.miss = function() {
            if (MUTEKI) return;
            if (this.killed) return;

            this.visible = false;
            this.killed = true;

            var explosion = new Sprite(64, 64);
            explosion.scaleX = 2;
            explosion.scaleY = 2;
            explosion.image = Dtype.game.assets["explosion2.png"];
            explosion.frame = 0;
            explosion.x = this.x + this.width / 2 - explosion.width / 2;
            explosion.y = this.y + this.height / 2 - explosion.height / 2;
            explosion.addEventListener("enterframe", function(e) {
                if (!this.parentNode) return;
                this.frame += 1;
                if (20 <= this.frame) {
                    this.removeEventListener(arguments.callee);
                    this.parentNode.removeChild(this);
                    Dtype.game.end(Dtype.game.score, "score = " + Dtype.game.score);
                    Dtype.game.stop();
                    console.log("game over");
                }
            });
            this.parentNode.addChild(explosion);
        };

        var touchStartX = 0;
        var touchStartY = 0;
        game.rootScene.addEventListener("touchstart", function(e) {
            if (myFighter.killed) return;

            touchStartX = e.localX;
            touchStartY = e.localY;
        });
        game.rootScene.addEventListener("touchmove", function(e) {
            if (myFighter.killed) return;

            var vx = e.localX - touchStartX;
            var vy = e.localY - touchStartY;
            if (Math.abs(vx) > myFighter.speed) {
                vx = myFighter.speed * vx / Math.abs(vx);
            }
            if (Math.abs(vy) > myFighter.speed) {
                vy = myFighter.speed * vy / Math.abs(vy);
            }
            myFighter.move(vx, vy);

            touchStartX = e.localX;
            touchStartY = e.localY;
        });
        myFighter.addEventListener("enterframe", function(e) {
            if (this.killed) return;

            var vx = 0;
            var vy = 0;
            if (game.input.up) vy = -1 * this.speed;
            if (game.input.right) vx = this.speed;
            if (game.input.down) vy = this.speed;
            if (game.input.left) vx = -1 * this.speed;

            this.move(vx, vy);
            
            if (this.x < 0) this.x = 0;
            if (game.width < this.x + this.width) this.x = game.width - this.width;
            if (this.y < 0) this.y = 0;
            if (game.height < this.y + this.height) this.y = game.height - this.height;

            // test
            if (game.input.b) {
                this.shotSpeed = 3;
                this.scaleX *= -1;
            } else {
                this.shotSpeed = 6;
                this.scaleX = 1;
            }

            if (!game.input.a && this.heat < 0) {
                var self = this;
                getReady(Dtype.bullets, function(b) {
                    b.ready = false;
                    b.x = self.x + self.width / 2;
                    b.y = self.y + self.height / 2;
                    stage.addChild(b);
                    self.heat = self.shotSpeed;
                });

                // test
                if (game.input.b) {
                    getReady(Dtype.bullets, function(b) {
                        b.ready = false;
                        b.x = self.x + self.width / 2;
                        b.y = self.y + self.height / 2 - 2;
                        stage.addChild(b);
                    });
                    getReady(Dtype.bullets, function(b) {
                        b.ready = false;
                        b.x = self.x + self.width / 2;
                        b.y = self.y + self.height / 2 + 2;
                        stage.addChild(b);
                    });
                }
            }
            this.heat -= 1;
        });

        stage.addEventListener("enterframe", function(e) {
            // myFighter and enemy hit test
            for (var i = 0; i < Dtype.enemies.length; i++) {
                if (Dtype.enemies[i].ready) continue;
                if (Dtype.enemies[i].within(myFighter, Dtype.enemies[i].hitSize + myFighter.hitSize)) {
                    Dtype.enemies[i].ready = false;
                    myFighter.miss();
                    return;
                }
            }

            // generate enemy
            if (game.frame % 30 == 0) {
                getReady(Dtype.enemies, function(e) {
                    var rnd = Math.floor(Math.random() * enemyData.length);
                    e.init(game.width - e.width, e.y = Math.random() * (game.height - e.height), enemyData[rnd]);
                });
            }
        });
    };
    game.start();
};

function createBackground() {
    var result = new Group();

    var background = new Sprite(Dtype.game.width, Dtype.game.height);
    var backgroundSurface = new Surface(Dtype.game.width, Dtype.game.height);
    background.image = backgroundSurface;
    var ctx = backgroundSurface.context;
    var stars = [];
    for(var i = 0; i < 50; i++) {
        stars.push({
            x : Math.random() * ctx.canvas.width,
            y : Math.random() * ctx.canvas.height,
            speed : 5 + Math.random() * 5,
            draw : function(_context) {
                this.x -= this.speed;
                _context.fillStyle = "#fff";
                _context.beginPath();
                _context.rect(this.x, this.y, 1, 1);
                _context.fill();
                
                if(this.x < 0) {
                    this.x = _context.canvas.width;
                }
            }
        });
    }
    background.addEventListener("enterframe", function(e) {
        backgroundSurface.clear();
        for(var i = 0; i < stars.length; i++) {
            stars[i].draw(ctx);
        }
    });
    
    return background;
}

function createMap() {
    var blocks = [
        [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
        [-1,-1,-1,-1,-1,-1,-1,-1, 1, 1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
        [-1,-1,-1,-1,-1,-1,-1,-1, 1, 1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
        [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
        [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
        [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
        [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
        [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
        [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 1, 1,-1,-1,-1,-1],
        [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 1, 1,-1,-1,-1,-1],
        [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
        [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
        [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
        [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
        [-1,-1,-1,-1,-1,-1,-1, 1, 1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
        [-1,-1,-1,-1,-1,-1,-1, 1, 1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
        [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
        [-1,-1,-1,-1,-1, 1, 1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
        [-1,-1,-1,-1,-1, 1, 1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
        [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
        [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
    ];
    var col = [];

    for (var i = 0; i < blocks.length; i++) {
        for (var j = 0; j < 10; j++) {
            blocks[i] = blocks[i].concat(blocks[i]);
        }
    }
    for (var i = 0; i < blocks.length; i++) {
        col[i] = [];
        for (var j = 0; j < blocks[i].length; j++) {
            col[i][j] = (blocks[i][j] != -1) ? 1 : 0;
        }
    }
    
    var map = new Map(16, 16);
    map.image = Dtype.game.assets['map2.gif'];
    map.loadData(blocks);
    map.collisionData = col;
    map.addEventListener("enterframe", function(e) {
        this.x -= SCROLL_SPEED;
    });

    return map;
}
